class Dog:
    def speak(self):
        return "Woof!"


class Cat:
    def speak(self):
        return "Meow!"

    # 动物工厂类


class AnimalFactory:
    @staticmethod
    def get_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            return None

        # 使用工厂类


if __name__ == "__main__":
    dog = AnimalFactory.get_animal("dog")
    if dog:
        print(dog.speak())

    cat = AnimalFactory.get_animal("cat")
    if cat:
        print(cat.speak())

        # 尝试获取不存在的动物类型
    unknown_animal = AnimalFactory.get_animal("bird")
    if not unknown_animal:
        print("Unsupported animal type.")

# 在上面的例子中，将对象的创建逻辑封装在一个工厂类中，并通过提供一个公共的接口来创建对象，从而隐藏了对象创建的具体实现细节，这句话的理解可以从以下几个方面展开：
# 对象的创建逻辑封装：在AnimalFactory类中，get_animal方法封装了创建Dog和Cat对象的逻辑。这个方法根据传入的参数（animal_type）决定要创建哪种类型的对象，并返回该对象的实例。这样，关于如何创建不同动物对象的细节就被封装在get_animal方法内部了。
# 公共的接口：get_animal方法作为AnimalFactory类的一个公共接口，允许外部代码通过调用这个方法来获取动物对象的实例，而不需要知道对象是如何被创建的。这个接口是公开的、可访问的，并且提供了一个统一的、标准化的方式来创建对象。
# 隐藏了对象创建的具体实现细节：当外部代码调用get_animal方法时，它不需要知道Dog和Cat对象是如何被实例化的，也不需要关心这些对象背后的具体实现细节。所有的这些都被封装在get_animal方法内部了。外部代码只需要知道它可以通过AnimalFactory类的get_animal方法来获取一个动物对象，并可以调用该对象的speak方法（在这个例子中）来执行一些操作。
# 提高代码的可维护性和可扩展性：通过将对象的创建逻辑封装在工厂类中，并提供一个公共的接口来访问这些对象，我们可以更容易地修改或扩展对象的创建逻辑，而不需要修改外部代码。例如，如果我们想要添加一个新的动物类型（比如Bird），我们只需要在AnimalFactory类中添加一个新的条件分支来创建Bird对象，而不需要修改任何已经使用AnimalFactory的代码。
# 这种设计模式的好处在于它降低了代码之间的耦合度，提高了代码的可重用性、可维护性和可扩展性。同时，它也使得代码更加清晰和易于理解，因为每个类都负责它自己的职责，而不是将多个职责混合在一起。

